package com.byapp.fast.amqp;

import com.byapp.fast.amqp.enums.AmqpEnum;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * AMQP配置
 */
@Configuration
public class AmqpConfig {


    /**
     * 交换机配置
     */
    private static class ExchangeConfig {
        /**
         * 直连交换机(模式)
         * 用于实例间的任务分发
         * 是一种带路由功能的交换机，一个队列会和一个交换机绑定，除此之外再绑定一个routing_key
         */
        @Bean
        public DirectExchange directExchange() {
            return new DirectExchange(AmqpEnum.ExchangeTypeEnum.DIRECT_EXCHANGE.getExchangeType());
        }

        /**
         * 扇形交换机(模式)
         * 分发给所有绑定到该exchange上的队列，忽略routing key
         * 速度是所有的交换机类型里面最快的
         */
        @Bean
        public FanoutExchange fanoutExchange() {
            return new FanoutExchange(AmqpEnum.ExchangeTypeEnum.FANOUT_EXCHANGE.getExchangeType());
        }

        /**
         * 主题交换机(模式)
         * 通过可配置的规则分发给绑定在该exchange上的队列
         * 发送到主题交换机上的消息需要携带指定规则的routing_key
         * 交换机和队列的binding_key需要采用*.#.*.....的格式，每个部分用.分开
         * *表示一个单词
         * #表示任意数量（零个或多个）单词
         */
        @Bean
        public TopicExchange topicExchange() {
            return new TopicExchange(AmqpEnum.ExchangeTypeEnum.TOPIC_EXCHANGE.getExchangeType());
        }

        /**
         * 首部交换机(模式)
         * 适用规则复杂的分发，用headers里的参数表达规则，有点像HTTP的Headers
         * 绑定交换机和队列的时候，Hash结构中要求携带一个键“x-match”，这个键的Value可以是any或者all，
         * 这代表消息携带的Hash是需要全部匹配(all)，还是仅匹配一个键(any)就可以了
         */
        @Bean
        public HeadersExchange headersExchange() {
            return new HeadersExchange(AmqpEnum.ExchangeTypeEnum.HEADERS_EXCHANGE.getExchangeType());
        }
    }


    /**
     * 消息队列配置
     */
    private static class QueuesConfig {

        @Bean
        public Queue matchOddsQueue() {
            return new Queue(AmqpEnum.MessageTypeEnum.MATCH_ODDS.getQueueName());
        }

        @Bean
        public Queue matchHandicapQueue() {
            return new Queue(AmqpEnum.MessageTypeEnum.MATCH_HANDICAP.getQueueName());
        }

        @Bean
        public Queue callBackPayQueue() {
            return new Queue(AmqpEnum.MessageTypeEnum.CALLBACK_PAY.getQueueName());
        }

        @Bean
        public Queue callBackEthQueue() {
            return new Queue(AmqpEnum.MessageTypeEnum.CALLBACK_ETH.getQueueName());
        }

        // 区块队列
        @Bean
        public Queue cbAddMatchQueue() {
            return new Queue(AmqpEnum.CTypeEnum.CALLBACK_ADD_MATCH.getQueueName());
        }

        @Bean
        public Queue cbAddPlayQueue() {
            return new Queue(AmqpEnum.CTypeEnum.CALLBACK_ADD_PLAY.getQueueName());
        }

        @Bean
        public Queue cbChangeOddsQueue() {
            return new Queue(AmqpEnum.CTypeEnum.CALLBACK_CHANGE_ODDS.getQueueName());
        }

        @Bean
        public Queue cbChangeHandicapQueue() {
            return new Queue(AmqpEnum.CTypeEnum.CALLBACK_CHANGE_HANDICAP.getQueueName());
        }

        @Bean
        public Queue cbChangeMatchQueue() {
            return new Queue(AmqpEnum.CTypeEnum.CALLBACK_CHANGE_MATCH.getQueueName());
        }

        @Bean
        public Queue cbAddBailQueue() {
            return new Queue(AmqpEnum.CTypeEnum.CALLBACK_ADD_BAIL.getQueueName());
        }

        @Bean
        public Queue cbCancelOrderQueue() {
            return new Queue(AmqpEnum.CTypeEnum.CALLBACK_CANCEL_ORDER.getQueueName());
        }

        @Bean
        public Queue cbCancelMatchQueue() {
            return new Queue(AmqpEnum.CTypeEnum.CALLBACK_CANCEL_MATCH.getQueueName());
        }

        @Bean
        public Queue cbLotMatchQueue() {
            return new Queue(AmqpEnum.CTypeEnum.CALLBACK_LOT_MATCH.getQueueName());
        }

        @Bean
        public Queue cbPrizeMatchQueue() {
            return new Queue(AmqpEnum.CTypeEnum.CALLBACK_PRIZE_MATCH.getQueueName());
        }

    }

    /**
     * 队列与交换机绑定配置
     */
    private static class BindingConfig {

        /**
         * 队列与直连交换机绑定
         */
        @Bean
        public Binding bindingMatchOddsWithDirect(DirectExchange direct, Queue matchOddsQueue) {
            return BindingBuilder.bind(matchOddsQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.MATCH_ODDS_DIRECT.getRoutingKey());
        }

        @Bean
        public Binding bindingMatchHandicapWithDirect(DirectExchange direct, Queue matchHandicapQueue) {
            return BindingBuilder.bind(matchHandicapQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.MATCH_HANDICAP_DIRECT.getRoutingKey());
        }

        @Bean
        public Binding bindingCallBackPayWithDirect(DirectExchange direct, Queue callBackPayQueue) {
            return BindingBuilder.bind(callBackPayQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CALLBACK_PAY_DIRECT.getRoutingKey());
        }

        @Bean
        public Binding bindingCallBackEthWithDirect(DirectExchange direct, Queue callBackEthQueue) {
            return BindingBuilder.bind(callBackEthQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CALLBACK_ETH_DIRECT.getRoutingKey());
        }

        // 区块回调绑定
        @Bean
        public Binding bindingCbAddMatchWithDirect(DirectExchange direct, Queue cbAddMatchQueue) {
            return BindingBuilder.bind(cbAddMatchQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CB_ADD_MATCH_DIRECT.getRoutingKey());
        }

        @Bean
        public Binding bindingCbAddPlayEthWithDirect(DirectExchange direct, Queue cbAddPlayQueue) {
            return BindingBuilder.bind(cbAddPlayQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CB_ADD_PLAY_DIRECT.getRoutingKey());
        }

        @Bean
        public Binding bindingCbChangeOddsWithDirect(DirectExchange direct, Queue cbChangeOddsQueue) {
            return BindingBuilder.bind(cbChangeOddsQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CB_CHANGE_ODDS_DIRECT.getRoutingKey());
        }

        @Bean
        public Binding bindingCbChangeHandicapWithDirect(DirectExchange direct, Queue cbChangeHandicapQueue) {
            return BindingBuilder.bind(cbChangeHandicapQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CB_CHANGE_HANDICAP_DIRECT.getRoutingKey());
        }

        @Bean
        public Binding bindingCbChangeMatchWithDirect(DirectExchange direct, Queue cbChangeMatchQueue) {
            return BindingBuilder.bind(cbChangeMatchQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CB_CHANGE_MATCH_DIRECT.getRoutingKey());
        }

        @Bean
        public Binding bindingCbAddBailEthWithDirect(DirectExchange direct, Queue cbAddBailQueue) {
            return BindingBuilder.bind(cbAddBailQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CB_ADD_BAIL_DIRECT.getRoutingKey());
        }

        @Bean
        public Binding bindingCbCancelOrderWithDirect(DirectExchange direct, Queue cbCancelOrderQueue) {
            return BindingBuilder.bind(cbCancelOrderQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CB_CANCEL_ORDER_DIRECT.getRoutingKey());
        }

        @Bean
        public Binding bindingCbCancelMatchWithDirect(DirectExchange direct, Queue cbCancelMatchQueue) {
            return BindingBuilder.bind(cbCancelMatchQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CB_CANCEL_MATCH_DIRECT.getRoutingKey());
        }


        @Bean
        public Binding bindingCbLotMatchWithDirect(DirectExchange direct, Queue cbLotMatchQueue) {
            return BindingBuilder.bind(cbLotMatchQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CB_LOT_MATCH_DIRECT.getRoutingKey());
        }

        @Bean
        public Binding bindingCbPrizeMatchWithDirect(DirectExchange direct, Queue cbPrizeMatchQueue) {
            return BindingBuilder.bind(cbPrizeMatchQueue)
                    .to(direct)
                    .with(AmqpEnum.RoutingKeyEnum.CB_PRIZE_MATCH_DIRECT.getRoutingKey());
        }

    }

}
